package org.vectrics.common.reporting.pdf;



import java.awt.Color;
import java.io.OutputStream;
import java.util.Locale;
import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfContentByte;
import org.apache.log4j.Logger;
import org.vectrics.VectricsException;
import org.vectrics.SystemException;
import org.vectrics.provider.CoreServiceLocator;


abstract public class BaseReport {
	private transient static Logger log = Logger.getLogger(BaseReport.class);

	private String author = "Unknown Author";
	private String subject = "Unknown Subject";
	//private RtfWriter2 writer = null;
	private PdfWriter pdfWriter = null;
	private float leftMargin = 50;
	private float rightMargin = 50;
	private float topMargin = 50;
	private float bottomMargin = 50;
	private Locale locale = null;
	private int chapterNumber = 1;

	
	private Document pdfDocument = null;
    private Font chapterFont = FontFactory.getFont(FontFactory.HELVETICA, 24, Font.NORMAL, new Color(0, 0, 0));
    private Font section1Font = FontFactory.getFont(FontFactory.HELVETICA, 20, Font.NORMAL, new Color(0, 0, 60));
    private Font section2Font = FontFactory.getFont(FontFactory.HELVETICA, 18, Font.NORMAL, new Color(0, 0, 60));
    private Font section3Font = FontFactory.getFont(FontFactory.HELVETICA, 16, Font.NORMAL, new Color(0, 0, 60));
    private Font section4Font = FontFactory.getFont(FontFactory.HELVETICA, 14, Font.NORMAL, new Color(0, 0, 60));
    private Font section5Font = FontFactory.getFont(FontFactory.HELVETICA, 13, Font.NORMAL, new Color(0, 0, 60));
    private Font section6Font = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.BOLD, new Color(0, 0, 60));
	
	
	
	public BaseReport(Locale locale) {
		this.locale = locale;
	}
	
	/**
	 * @return Returns the document.
	 */
	public Document getDocument() {
		return pdfDocument;
	}
	/**
	 * @return Returns the locale.
	 */
	public Locale getLocale() {
		return locale;
	}

	protected abstract void fill(Document document) throws VectricsException;

	protected void onDocumentStart(Document document)  throws VectricsException {
		log.debug("onDocumentStart() - no action");
	}

	protected void onDocumentEnd(Document document)  throws VectricsException {
		log.debug("onDocumentEnd() - no action");
	}
	
	
	protected Rectangle getPageSize() {
		return(PageSize.A4);
	}

	protected final PdfContentByte getDirectContent() {    
		PdfContentByte cb = pdfWriter.getDirectContent();
		return(cb);
	}
	
	//protected final RtfWriter2 getWriter() {
	//	return(writer);
	//}
	
	protected final PdfWriter getPdfWriter() {
		return(pdfWriter);
	}

	protected void onStartPage(PdfWriter writer, Document document) throws VectricsException {
		log.debug("onStartPage() - no action");
	}
	
	protected void onEndPage(PdfWriter writer, Document document) throws VectricsException {
		log.debug("onEndPage() - no action");
	}
    
	
	public void build(OutputStream outStream) throws VectricsException {
		log.debug("build() called");
			
		// creation of the document with a certain size and certain margins
		pdfDocument = new Document(getPageSize(), getLeftMargin(), getTopMargin(), 
				getRightMargin(), getBottomMargin());

        //writer = RtfWriter2.getInstance(document, outStream);
        //writer.setAutogenerateTOCEntries(true);

        try {
			// creation of the different writers
			pdfWriter = PdfWriter.getInstance(pdfDocument, outStream);
			BasePageEvent pageEvent = new BasePageEvent(this);
			
			pdfWriter.setPageEvent(pageEvent);
						
			pdfDocument.addAuthor(getAuthor());
			pdfDocument.addSubject(getSubject());
			
			pdfDocument.open();
			this.onDocumentStart(pdfDocument);
			fill(pdfDocument);
			this.onDocumentEnd(pdfDocument);
			// we close the document
			pdfDocument.close();
			
		}
		catch(Exception e) {
			log.error("Exception creating pdf document", e);
			throw new VectricsException("Exception creating pdf document", e);
		}
        
		// we close the document
		pdfDocument.close();
	}
	

	/**
	 * @return
	 */
	public String getAuthor() {
		return author;
	}

	/**
	 * @param author
	 */
	public void setAuthor(String author) {
		this.author = author;
	}

	protected Chapter createChapter(String name) {
        Paragraph cTitle = new Paragraph(name, chapterFont);
        Chapter chapter = new Chapter(cTitle, chapterNumber);
		chapterNumber++;
		
	    Font blankLineFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new Color(0, 0, 0));
        Paragraph blankLine = new Paragraph(" ", blankLineFont);
	    chapter.add(blankLine);
		
		return(chapter);
	}

	
	protected Section createSection(Chapter chapter, String name, int depth) {
		
		Font font = null;
		if (depth == 1) { 
			font = this.section1Font;
		} else if (depth == 2) { 
			font = this.section2Font;
		} else if (depth == 3) {
			font = this.section3Font;
		} else if (depth == 4) {
			font = this.section4Font;
		} else if (depth == 5) {
			font = this.section5Font;
		} else if (depth == 6) {
			font = this.section6Font;
		} else {
			throw new SystemException("Cannot find font for section depth = " + depth);
		}
		
        Paragraph cTitle = new Paragraph(name, font);
        Section section = chapter.addSection(cTitle, depth + 1);

        Font blankLineFont = FontFactory.getFont(FontFactory.HELVETICA, 6 + (depth), 
        		Font.NORMAL, new Color(0, 0, 0));
        Paragraph blankLine = new Paragraph(" ", blankLineFont);
	    section.add(blankLine);
		return(section);
	}
	
	
	/**
	 * @return
	 */
	public String getSubject() {
		return subject;
	}

	/**
	 * @param subject
	 */
	public void setSubject(String subject) {
		this.subject = subject;
	}

	/**
	 * @return
	 */
	public float getBottomMargin() {
		return bottomMargin;
	}

	/**
	 * @param bottomMargin
	 */
	public void setBottomMargin(float bottomMargin) {
		this.bottomMargin = bottomMargin;
	}

	/**
	 * @return
	 */
	public float getLeftMargin() {
		return leftMargin;
	}

	/**
	 * @param leftMargin
	 */
	public void setLeftMargin(float leftMargin) {
		this.leftMargin = leftMargin;
	}

	/**
	 * @return
	 */
	public float getRightMargin() {
		return rightMargin;
	}

	/**
	 * @param rightMargin
	 */
	public void setRightMargin(float rightMargin) {
		this.rightMargin = rightMargin;
	}

	/**
	 * @return
	 */
	public float getTopMargin() {
		return topMargin;
	}

	/**
	 * @param topMargin
	 */
	public void setTopMargin(float topMargin) {
		this.topMargin = topMargin;
	}
	
	public void addCodedParagraph(String phraseCode, Font font) {
		String phrase = CoreServiceLocator.getPhraseProvider().getMessage(phraseCode, locale);
		try {
			pdfDocument.add(new Paragraph(phrase, font));
		} catch (DocumentException de) {
			throw new SystemException("DocumentException making paragraph", de);
		}
	}
	
	public String getPhrase(String code) {
	    return(CoreServiceLocator.getPhraseProvider().getMessage(code, this.getLocale()));
	}

}
